// 内存相关操作安全包装

use thiserror::Error;
use super::api;
use super::capability::ThreadSafeCapability;
use crate::{SafeMemoryBuffer, FFIError};
use super::super::core::types::{PhysicalAddress, VirtualAddress, MemoryPermissions};

// 定义内存错误类型
#[derive(Error, Debug)]
pub enum MemoryError {
    #[error("Memory allocation failed")]
    AllocationFailed,
    
    #[error("Memory free failed")]
    FreeFailed,
    
    #[error("Memory mapping failed")]
    MappingFailed,
    
    #[error("Memory unmapping failed")]
    UnmappingFailed,
    
    #[error("Invalid memory size")]
    InvalidSize,
    
    #[error("Invalid memory address")]
    InvalidAddress,
    
    #[error("Invalid memory permissions")]
    InvalidPermissions,
    
    #[error("FFI error: {0}")]
    FFIError(#[from] FFIError),
}

// 定义内存结果类型
pub type MemoryResult<T> = Result<T, MemoryError>;

// 安全的物理内存块包装器
pub struct PhysicalMemoryBlock {
    capability: ThreadSafeCapability,
    address: PhysicalAddress,
    size: u64,
    alignment: u64,
}

impl PhysicalMemoryBlock {
    // 分配物理内存
    pub fn allocate(capability: ThreadSafeCapability, size: u64, alignment: u64) -> MemoryResult<Self> {
        // 验证能力是否为内存类型
        if let Ok(cap) = capability.lock() {
            if cap.resource_type() != super::super::core::types::ResourceType::Memory {
                return Err(MemoryError::AllocationFailed);
            }
        } else {
            return Err(MemoryError::AllocationFailed);
        }
        
        // 验证大小是否有效
        if size == 0 {
            return Err(MemoryError::InvalidSize);
        }
        
        // 获取能力ID
        let cap_id = if let Ok(cap) = capability.lock() {
            cap.id()
        } else {
            return Err(MemoryError::AllocationFailed);
        };
        
        // 调用FFI分配物理内存
        let address = unsafe {
            api::exokernel_allocate_physical_memory(cap_id, size, alignment)
        };
        
        // 检查分配是否成功（假设0表示失败）
        if address == 0 {
            return Err(MemoryError::AllocationFailed);
        }
        
        Ok(PhysicalMemoryBlock {
            capability,
            address,
            size,
            alignment,
        })
    }
    
    // 获取物理地址
    pub fn address(&self) -> PhysicalAddress {
        self.address
    }
    
    // 获取大小
    pub fn size(&self) -> u64 {
        self.size
    }
    
    // 获取对齐方式
    pub fn alignment(&self) -> u64 {
        self.alignment
    }
    
    // 映射物理内存到虚拟地址空间
    pub fn map(&self, virt_addr: VirtualAddress, perms: MemoryPermissions) -> MemoryResult<bool> {
        // 获取能力ID
        let cap_id = if let Ok(cap) = self.capability.lock() {
            cap.id()
        } else {
            return Err(MemoryError::MappingFailed);
        };
        
        // 调用FFI映射内存
        let result = unsafe {
            api::exokernel_map_memory(cap_id, virt_addr, self.address, self.size, perms)
        };
        
        if result {
            Ok(true)
        } else {
            Err(MemoryError::MappingFailed)
        }
    }
}

// 实现Drop以确保物理内存被正确释放
impl Drop for PhysicalMemoryBlock {
    fn drop(&mut self) {
        // 获取能力ID
        let cap_id = if let Ok(cap) = self.capability.lock() {
            cap.id()
        } else {
            return;
        };
        
        // 调用FFI释放物理内存
        unsafe {
            api::exokernel_free_physical_memory(cap_id, self.address, self.size);
        }
    }
}

// 安全的内存映射包装器
pub struct MemoryMapping {
    capability: ThreadSafeCapability,
    virt_addr: VirtualAddress,
    phys_addr: PhysicalAddress,
    size: u64,
    perms: MemoryPermissions,
}

impl MemoryMapping {
    // 创建内存映射
    pub fn new(
        capability: ThreadSafeCapability,
        virt_addr: VirtualAddress,
        phys_addr: PhysicalAddress,
        size: u64,
        perms: MemoryPermissions
    ) -> MemoryResult<Self> {
        // 验证能力是否为内存类型
        if let Ok(cap) = capability.lock() {
            if cap.resource_type() != super::super::core::types::ResourceType::Memory {
                return Err(MemoryError::MappingFailed);
            }
        } else {
            return Err(MemoryError::MappingFailed);
        }
        
        // 验证大小是否有效
        if size == 0 {
            return Err(MemoryError::InvalidSize);
        }
        
        // 获取能力ID
        let cap_id = if let Ok(cap) = capability.lock() {
            cap.id()
        } else {
            return Err(MemoryError::MappingFailed);
        };
        
        // 调用FFI创建内存映射
        let result = unsafe {
            api::exokernel_map_memory(cap_id, virt_addr, phys_addr, size, perms)
        };
        
        if result {
            Ok(MemoryMapping {
                capability,
                virt_addr,
                phys_addr,
                size,
                perms,
            })
        } else {
            Err(MemoryError::MappingFailed)
        }
    }
    
    // 获取虚拟地址
    pub fn virt_addr(&self) -> VirtualAddress {
        self.virt_addr
    }
    
    // 获取物理地址
    pub fn phys_addr(&self) -> PhysicalAddress {
        self.phys_addr
    }
    
    // 获取大小
    pub fn size(&self) -> u64 {
        self.size
    }
    
    // 获取权限
    pub fn permissions(&self) -> MemoryPermissions {
        self.perms
    }
    
    // 安全地访问映射的内存
    pub fn access_memory(&self) -> MemoryResult<SafeMemoryBuffer> {
        // 在实际实现中，这里可能需要更复杂的逻辑来安全地访问映射的内存
        // 这里简化处理，创建一个大小相同的缓冲区
        SafeMemoryBuffer::new(self.size as usize)
            .map_err(MemoryError::FFIError)
    }
}

// 实现Drop以确保内存映射被正确解除
impl Drop for MemoryMapping {
    fn drop(&mut self) {
        // 获取能力ID
        let cap_id = if let Ok(cap) = self.capability.lock() {
            cap.id()
        } else {
            return;
        };
        
        // 调用FFI解除内存映射
        unsafe {
            api::exokernel_unmap_memory(cap_id, self.virt_addr, self.size);
        }
    }
}